#include "serial.h"
#include "ui_serial.h"
#include "pointcloudvisualization.h"

Serial::Serial(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Serial) {
    ui->setupUi(this);

    serialBase = new QSerialPort();//串口类

    timer_serialMsgUpdate = new QTimer(this);
    connect(timer_serialMsgUpdate, &QTimer::timeout, this, &Serial::serialReceiveDisplayEvent);
    connect(timer_serialMsgUpdate, &QTimer::timeout, this, &Serial::serialReceiveToPiontCloud);
    timer_serialMsgUpdate->start(10);

    /*界面初始化*/
    ui->lineEdit_Vel->setText("2000");
    ui->lineEdit_PointDis->setText("10");
    ui->lineEdit_ScanDis->setText("300");

    /*按键连接*/
    connect(ui->pushButton_updateSerial, &QPushButton::clicked, this, &Serial::serialNumUpdate);
    connect(ui->pushButton_serialClaerReceive, &QPushButton::clicked, this, &Serial::onBtnClearReceive_clicked);
    connect(ui->pushButton_serialOpenOrClose, &QPushButton::clicked, this, &Serial::onBtnOpenOrColse_clicked);
    connect(ui->pushButton_Start, &QPushButton::clicked, this, &Serial::onBtnStart_clicked);
    connect(ui->pushButton_Pause, &QPushButton::clicked, this, &Serial::onBtnPause_clicked);
    connect(ui->pushButton_Stop, &QPushButton::clicked, this, &Serial::onBtnStop_clicked);


}

void Serial::init() {
    QList<QSerialPortInfo> comList = QSerialPortInfo::availablePorts();//获取可用的串口号

    ui->comboBox_serialNum->clear();//清空item，避免搜索后重复添加
    ui->comboBox_serialBound->clear();
    ui->comboBox_serialDataBits->clear();
    ui->comboBox_serialCheckBits->clear();
    ui->comboBox_serialStopBits->clear();

//    if(comList.isEmpty()) { //若没有可用串口，则发送警告
//        QMessageBox::warning(this, "Waring!", "There's no avalible COM to use, plese check your serialport!");
//    } else { //将可用串口显示到comboBox上以供选择
    for(int i = 0; i < comList.size(); i ++) {
        ui->comboBox_serialNum->addItem(comList[i].portName());
        //ui->cBox_SerialPortNum->addItem(comList[i].description());//设备描述
    }

//    }

    QStringList baudRateList = QStringList() << "1200" << "2400" << "4800"
                               << "9600" << "14400" << "19200" << "38400" << "43000" << "57600"
                               << "76800" << "115200" << "128000" << "230400" << "256000" << "460800"
                               << "921600" << "1382400";
    QStringList parityList = QStringList() << "无" << "奇校验" << "偶校验";
    QStringList stopBitsList = QStringList() << "1" << "1.5" << "2";
    QStringList dataBitsList = QStringList() << "8" << "7" << "6" << "5";

    ui->comboBox_serialBound->addItems(baudRateList);
    ui->comboBox_serialBound->setCurrentIndex(10);  //默认115200
    ui->comboBox_serialCheckBits->addItems(parityList);
    ui->comboBox_serialDataBits->addItems(dataBitsList);
    ui->comboBox_serialStopBits->addItems(stopBitsList);
}

void Serial::serialNumUpdate() {    //定时刷新可用串口号
    QList<QSerialPortInfo> comList = QSerialPortInfo::availablePorts();//获取可用的串口号

    ui->comboBox_serialNum->clear();

    for(int i = 0; i < comList.size(); i ++) {
        ui->comboBox_serialNum->addItem(comList[i].portName());
    }
}

void Serial::serialReceiveDisplayEvent() {
    QByteArray bufferHex = str_buffer_Serial.toHex();//转换成hex
    bufferHex = bufferHex.toUpper(); //转换成大写
    QString str_buffer1;

    //16进制显示
    str_buffer1 = QString(bufferHex);//转换成字符

    for(int i = str_buffer1.count(); i > 0; i = i - 2) {
        str_buffer1.insert(i, " ");
    }

    if(ui->pushButton_serialOpenOrClose->text() == "关闭串口") {
        ui->serialDataReceiveDisplay->insertPlainText(str_buffer1);
        ui->serialDataReceiveDisplay->moveCursor(QTextCursor::End);
    }

    str_buffer1 = ui->serialDataReceiveDisplay->toPlainText();

    if(str_buffer1.size() > 10000) {
        ui->serialDataReceiveDisplay->clear();
    }

    str_buffer_Serial.clear();
}

void Serial::serialReceiveToPiontCloud() {//将接收到的数据传送给点云绘制库
    QByteArray lidar_start = QByteArray::fromHex("A55A0500004081");
    QByteArray lidar_end = QByteArray::fromHex("FFFF");
    int index = -1;

    if(pointCloud_buffer_Serial.endsWith(lidar_end)) { //一组数据接收完成开始处理
        index = pointCloud_buffer_Serial.indexOf(lidar_start);

        if(index != -1) {
            PointCloud_t PointCloud;
            uint8_t quality, angle_L, angle_H, distance_L, distance_H, height_H, height_L;
            float angle_f, distance_f;
            uint16_t height;
            int len;

            len = pointCloud_buffer_Serial.size();
            height_H = pointCloud_buffer_Serial.at(len - 4);
            height_L = pointCloud_buffer_Serial.at(len - 3);
            height = ((uint16_t)height_H << 8) | height_L;
            index += 7;

            for(int i = 0; i < (len - index - 4) / 5; i++) {
                quality = pointCloud_buffer_Serial[index++];
                angle_L = pointCloud_buffer_Serial[index++];
                angle_H = pointCloud_buffer_Serial[index++];
                distance_L = pointCloud_buffer_Serial[index++];
                distance_H = pointCloud_buffer_Serial[index++];

                /***TX：A5 20 //开始扫描
                    RX：A5 5A 05 00 00 40 81 //应答信号

                    25 //0010 0101 //Quality     		末位为1，表示新的一圈的开始
                    C5 //1100 0101 //angle_q6[6:0]		最后一位永远是1
                    9B //1001 1011 //angle_q6[14:7]		311.53度 angle_q6/64deg
                    2D //0010 1101 //distance_q2[7:0]
                    0A //0000 1010 //distance_q2[15:8]	651.25mm distance_q2/4mm
                */

                angle_f = (float)((((uint16_t)angle_H << 8 | angle_L)) >> 1) / 64.0f;
                angle_f = angle_f * PI / 180;//化为弧度制
                distance_f = (float)((uint16_t)distance_H << 8 | distance_L) / 4.0f;

                PointCloud.quality = quality >> 1;
                PointCloud.num = i + 1;
                PointCloud.height = (float)height / 10;
                //PointCloud.point = QVector3D(distance_f * cosf(angle_f), PointCloud.height, distance_f * sinf(angle_f)); //YZ对调
                PointCloud.point = QVector3D(distance_f * sinf(angle_f), PointCloud.height, distance_f * cosf(angle_f));
                d_queue.append(PointCloud);
            }

            emit this->pointDataReady();
        }

        pointCloud_buffer_Serial.clear();
    }
}

void Serial::serialPort_getdata() {
    qint64 byteLen_now = serialBase->bytesAvailable();

    if(byteLen_now < 0) {
        return;
    }

    //qDebug()<<"当前缓存长度"<<byteLen_now<<endl;

    buffer_Serial += serialBase->readAll();

//    QByteArray bufferHex = buffer_Serial.toHex();//转换成hex
//    bufferHex = bufferHex.toUpper(); //转换成大写
    str_buffer_Serial += buffer_Serial;
    pointCloud_buffer_Serial += buffer_Serial;
//    QString str_buffer = QString(bufferHex);//转换成字符

//    for(int i = str_buffer.count(); i > 0; i = i - 2) {
//        str_buffer.insert(i, " ");
//    }

    buffer_Serial.clear();
}

void Serial::onBtnClearReceive_clicked() {
    ui->serialDataReceiveDisplay->clear();
}


void Serial::onBtnOpenOrColse_clicked() { //打开或关闭串口
    if(ui->pushButton_serialOpenOrClose->text() == "打开串口") {
        serialBase->setPortName(ui->comboBox_serialNum->currentText());//设置串口
        serialBase->setBaudRate(ui->comboBox_serialBound->currentText().toInt());

        switch(ui->comboBox_serialCheckBits->currentIndex()) { //设置数据校验形式
        case 0:
            serialBase->setParity(QSerialPort::NoParity);//无校验
            break;

        case 1:
            serialBase->setParity(QSerialPort::OddParity);//奇校验
            break;

        case 2:
            serialBase->setParity(QSerialPort::EvenParity);//偶校验
            break;

        default:
            serialBase->setParity(QSerialPort::NoParity);
            break;
        }

        switch(ui->comboBox_serialDataBits->currentIndex()) { //设置数据位
        case 0:
            serialBase->setDataBits(QSerialPort::Data8);
            break;

        case 1:
            serialBase->setDataBits(QSerialPort::Data7);
            break;

        case 2:
            serialBase->setDataBits(QSerialPort::Data6);
            break;

        case 3:
            serialBase->setDataBits(QSerialPort::Data5);
            break;

        default:
            serialBase->setDataBits(QSerialPort::Data8);
            break;
        }

        switch(ui->comboBox_serialStopBits->currentIndex()) { //设置停止位
        case 0:
            serialBase->setStopBits(QSerialPort::OneStop);
            break;

        case 1:
            serialBase->setStopBits(QSerialPort::OneAndHalfStop);
            break;

        case 2:
            serialBase->setStopBits(QSerialPort::TwoStop);
            break;

        default:
            serialBase->setStopBits(QSerialPort::OneStop);
            break;
        }

        serialBase->setFlowControl(QSerialPort::NoFlowControl); //无流控
        serialBase->setReadBufferSize(8192);                    //数据缓冲区长度
        bool bOK = serialBase->open(QIODevice::ReadWrite);

        if(!bOK) {
            //qDebug("test is ok");
            QMessageBox::critical(this, "提示", "无法打开串口，请检查是否被占用。", QMessageBox::Yes, QMessageBox::Yes);
            return;
        }

        connect(serialBase, &QSerialPort::readyRead, this, &Serial::serialPort_getdata, Qt::DirectConnection); //连接串口接收信号与槽函数

        ui->comboBox_serialNum->setEnabled(false);
        ui->comboBox_serialBound->setEnabled(false);
        ui->comboBox_serialCheckBits->setEnabled(false);
        ui->comboBox_serialDataBits->setEnabled(false);
        ui->comboBox_serialStopBits->setEnabled(false);
        ui->pushButton_updateSerial->setEnabled(false);

        ui->pushButton_serialOpenOrClose->setText("关闭串口");
    } else {
        ui->pushButton_serialOpenOrClose->setText("打开串口");
        serialBase->close();

        ui->comboBox_serialNum->setEnabled(true);
        ui->comboBox_serialBound->setEnabled(true);
        ui->comboBox_serialCheckBits->setEnabled(true);
        ui->comboBox_serialDataBits->setEnabled(true);
        ui->comboBox_serialStopBits->setEnabled(true);
        ui->pushButton_updateSerial->setEnabled(true);
    }
}


void Serial::onBtnStart_clicked() {
    QByteArray scan_start = QByteArray::fromHex("FA00");
    ushort Vel, PointDis, ScanDis;
    uint8_t Vel_H, Vel_L, PointDis_u8, ScanDis_H, ScanDis_L, End = 0xFB;

    Vel = ui->lineEdit_Vel->text().toUShort();
    Vel_H = (Vel >> 8) & 0xFF;
    Vel_L = Vel & 0xFF;
    scan_start.append(Vel_H).append(Vel_L);

    PointDis = ui->lineEdit_PointDis->text().toUShort();
    PointDis_u8 = PointDis & 0xFF;
    scan_start.append(PointDis_u8);

    ScanDis = ui->lineEdit_ScanDis->text().toUShort();
    ScanDis_H = (ScanDis >> 8) & 0xFF;
    ScanDis_L = ScanDis & 0xFF;
    scan_start.append(ScanDis_H).append(ScanDis_L);

    scan_start.append(End);
    serialBase->write(scan_start);
}
void Serial::onBtnPause_clicked() {
    QByteArray scan_pause = QByteArray::fromHex("FA010000000000FB");

    serialBase->write(scan_pause);

}
void Serial::onBtnStop_clicked() {
    QByteArray scan_stop = QByteArray::fromHex("FA020000000000FB");

    serialBase->write(scan_stop);
}

Serial::~Serial() {
    serialBase->close();
    delete serialBase;
    delete ui;
}
